home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
AMIGA-CD 2
/
Amiga-CD - Volume 2.iso
/
gepackte_disketten
/
1994
/
08_94_5.dms
/
08_94_5.adf
/
term-4.0-Source.lha
/
termLocale.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-07-15
|
17KB
|
876 lines
/*
** termLocale.c
**
** Localization support routines
**
** Copyright © 1990-1994 by Olaf `Olsen' Barthel
** All Rights Reserved
*/
#include "termGlobal.h"
/* The catalog data is stored in the following format. */
struct CatCompArrayType
{
LONG cca_ID;
STRPTR cca_Str;
};
extern struct CatCompArrayType *AppStrings;
extern LONG NumAppStrings;
/* LocaleOpen(STRPTR CatalogName,STRPTR BuiltIn):
*
* Open string translation tables.
*/
VOID __regargs
LocaleOpen(STRPTR CatalogName,STRPTR BuiltIn,LONG Version)
{
if(LocaleBase = (struct LocaleBase *)OpenLibrary("locale.library",38))
{
if(LocaleBase -> lb_SysPatches)
{
strcpy(ConvNumber,"%lD");
strcpy(ConvNumber10,"%10lD");
if(Catalog = OpenCatalog(NULL,CatalogName,
OC_BuiltInLanguage, BuiltIn,
OC_BuiltInCodeSet, 0,
TAG_DONE))
{
BOOL TooOld = FALSE;
// Don't load an outdated catalog file
if(Catalog -> cat_Version < Version)
TooOld = TRUE;
else
{
if(strcmp(GetCatalogStr(Catalog,MSG_OFFSET_TEST1_TXT,""),"v4.0"))
TooOld = TRUE;
}
if(TooOld)
{
if(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0))
{
MyEasyRequest(NULL,"The catalog file is too old to be used\nwith this `term' revision.","Continue");
CloseLibrary(IntuitionBase);
IntuitionBase = NULL;
}
CloseCatalog(Catalog);
Catalog = NULL;
}
}
Locale = OpenLocale(NULL);
}
else
{
if(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0))
{
MyEasyRequest(NULL,"Your \"locale.library\" is not installed correctly.","Continue");
CloseLibrary(IntuitionBase);
IntuitionBase = NULL;
}
strcpy(ConvNumber,"%ld");
strcpy(ConvNumber10,"%10ld");
CloseLibrary(LocaleBase);
LocaleBase = NULL;
}
}
else
{
strcpy(ConvNumber,"%ld");
strcpy(ConvNumber10,"%10ld");
}
}
/* LocaleClose():
*
* Close the translation tables.
*/
VOID
LocaleClose()
{
if(Locale)
{
CloseLocale(Locale);
Locale = NULL;
}
if(Catalog)
{
CloseCatalog(Catalog);
Catalog = NULL;
}
if(LocaleBase)
{
CloseLibrary(LocaleBase);
LocaleBase = NULL;
}
}
/* LanguageCheck():
*
* Checks to see if the currently selected language
* is english.
*/
VOID
LanguageCheck()
{
if(Locale && Catalog)
{
if(Locale -> loc_LanguageName)
{
if(!Stricmp(Locale -> loc_LanguageName,"english.language"))
English = TRUE;
else
English = FALSE;
}
else
English = FALSE;
}
else
English = TRUE;
}
/* GadToolsStrlen(STRPTR *String):
*
* Custom version of strlen, useful for gadtools object titles
* with embedded underscore characters.
*/
WORD __regargs
GadToolsStrlen(STRPTR String)
{
WORD Len = 0;
while(*String)
{
if(*String++ != '_')
Len++;
}
return(Len);
}
/* GadToolsLongestString(WORD From,WORD To):
*
* Determines the longest string used by a gadtools
* control panel.
*/
WORD __regargs
GadToolsLongestString(WORD From,WORD To)
{
STRPTR Text;
WORD MaxLen = 0,
Len,i;
for(i = From ; i <= To ; i++)
{
if(Text = LocaleString(i))
{
if((Len = GadToolsStrlen(Text)) > MaxLen)
MaxLen = Len;
}
}
return(MaxLen);
}
/* LocaleSeconds(WORD Seconds):
*
* Return seconds in proper format.
*/
STRPTR __regargs
LocaleSeconds(WORD Seconds)
{
STATIC UBYTE Time[10];
if(Locale)
SPrintf(Time,"%2lD%s%02lD",Seconds / 100,Locale -> loc_DecimalPoint,Seconds % 100);
else
SPrintf(Time,"%2ld.%02ld",Seconds / 100,Seconds % 100);
return(Time);
}
/* SmallCurrency():
*
* Support function for the rates control panel, returns a formatted
* string to contain a string like "cents/unit".
*/
STRPTR
SmallCurrency()
{
STATIC UBYTE Buffer[30];
if(Locale)
SPrintf(Buffer,LocaleString(MSG_RATEPANEL_PAY_PER_UNIT_GAD),Locale -> loc_MonSmallCS);
else
SPrintf(Buffer,LocaleString(MSG_RATEPANEL_PAY_PER_UNIT_GAD),"Pay");
return(Buffer);
}
/* InsertGrouping(STRPTR Buffer,STRPTR GroupData,STRPTR GroupSeparator):
*
* Tricky stuff, folks! This beauty will insert grouping characters
* into a readily-prepared string buffer filled with numeric
* contents. It takes the group separator tokens and group separator
* strings into account.
*/
VOID __regargs
InsertGrouping(STRPTR Buffer,STRPTR GroupData,STRPTR GroupSeparator)
{
UBYTE LocalBuffer[80]; // Sufficient, but too large
STRPTR Index;
LONG i,j,SeparatorSize;
WORD Count; // How many characters per group
BOOL RepeatGroupCount; // Keep repeating group size until end
// Set up for the first group
switch(*GroupData)
{
case 0: // Repeat current grouping scheme until end
case 255: // No further grouping is to be performed
Count = 0;
break;
default: // Initial group size
RepeatGroupCount = FALSE;
Count = *GroupData++;
break;
}
// Check the size of the group separator string
if((SeparatorSize = strlen(GroupSeparator) - 1) < 1)
Count = 0;
// That where we'll start
Index = LocalBuffer;
// Build the string back to front, we will reverse it later
for(i = strlen(Buffer) - 1, j = 1 ; i >= 0 ; i--, j++)
{
// Pick up the next number character
*Index++ = Buffer[i];
// Are we to insert the grouping characters here?
if(Count && j == Count)
{
LONG k;
// Insert the grouping characters
for(k = SeparatorSize ; k >= 0 ; k--)
*Index++ = GroupSeparator[k];
// Reset the group size counter
j = 0;
// Pick up the next grouping token?
if(!RepeatGroupCount)
{
// Ok, what kind of token is it?
switch(*GroupData)
{
case 0: // Repeat current grouping scheme
RepeatGroupCount = TRUE;
break;
case 255: // Perform no further grouping
Count = 0;
break;
default: // New group size
Count = *GroupData++;
break;
}
}
}
}
// Look how long the resulting string is
j = (LONG)((ULONG)Index - (ULONG)LocalBuffer) - 1;
// Copy it back
Index = Buffer;
// Reverse the order of characters while copying
for(i = j ; i >= 0 ; i--)
*Index++ = LocalBuffer[i];
// Provide null-termination
*Index = 0;
}
VOID __regargs
ConvertMonetaryQuantity(LONG Units,STRPTR Destination,BOOL UseCurrency)
{
UBYTE IntegerBuffer[80]; // Sufficient, but too large
STRPTR SignText, // Signed/unsigned quantity text
SpaceText, // Currency/number separation
Currency; // The name of the currency
UBYTE SpaceSep, // A space separates currency and quantity?
SignPos, // Where to place the sign text
CSPos; // Where to place the currency text
BYTE Sign; // Negative or positive quantity?
// Negative quantity?
if(Units < 0)
{
Sign = -1;
Units = -Units;
}
else
Sign = 1;
// Does this currency sport a fractional smaller currency?
if(Locale -> loc_MonFracDigits)
{
UBYTE NumberBuffer[5],
FractionBuffer[40];
LONG Integer,
Fraction,
Scale;
WORD i;
// Prepare the formatting string
SPrintf(NumberBuffer,"%%0%ldld",Locale -> loc_MonFracDigits);
// Turn the number of fractional digits into a power of ten
for(i = 0, Scale = 1 ; i < Locale -> loc_MonFracDigits ; i++)
Scale *= 10;
// Split the quantity in integer and fractional part
Integer = Units / Scale;
Fraction = Units % Scale;
// Build the integer text
SPrintf(IntegerBuffer,"%ld",Integer);
InsertGrouping(IntegerBuffer,Locale -> loc_MonGrouping,Locale -> loc_MonGroupSeparator);
// Build the fractional text
SPrintf(FractionBuffer,NumberBuffer,Fraction);
InsertGrouping(FractionBuffer,Locale -> loc_MonFracGrouping,Locale -> loc_MonFracGroupSeparator);
// Add the monetary decimal point
strcat(IntegerBuffer,Locale -> loc_MonDecimalPoint);
// Add the fractional part
strcat(IntegerBuffer,FractionBuffer);
}
else
{
// Build the integer text
SPrintf(IntegerBuffer,"%ld",Units);
InsertGrouping(IntegerBuffer,Locale -> loc_MonGrouping,Locale -> loc_MonGroupSeparator);
}
// Pick up the appropriate formatting parameters
if(Sign < 0)
{
SignText = Locale -> loc_MonNegativeSign;
SpaceSep = Locale -> loc_MonNegativeSpaceSep;
SignPos = Locale -> loc_MonNegativeSignPos;
CSPos = Locale -> loc_MonNegativeCSPos;
}
else
{
SignText = Locale -> loc_MonPositiveSign;
SpaceSep = Locale -> loc_MonPositiveSpaceSep;
SignPos = Locale -> loc_MonPositiveSignPos;
CSPos = Locale -> loc_MonPositiveCSPos;
}
// Are we to use the currency symbol?
if(UseCurrency)
{
// Pick up the currency text
Currency = Locale -> loc_MonCS;
// Take care of the separation information
if(SpaceSep == SS_NOSPACE)
SpaceText = "";
else
SpaceText = " ";
}
else
Currency = SpaceText = "";
// Now merge all the information into one single string
if(CSPos == CSP_PRECEDES)
{
switch(SignPos)
{
case SP_PARENS:
// Currency (Space) Sign Value
SPrintf(Destination,"(%s%s%s%s)",Currency,SpaceText,SignText,IntegerBuffer);
break;
case SP_PREC_ALL:
// Sign Currency (Space) Value
SPrintf(Destination,"%s%s%s%s",SignText,Currency,SpaceText,IntegerBuffer);
break;
case SP_SUCC_ALL:
// Currency (Space) Value Sign
SPrintf(Destination,"%s%s%s%s",Currency,SpaceText,IntegerBuffer,SignText);
break;
case SP_PREC_CURR:
// Sign Currency (Space) Value
SPrintf(Destination,"%s%s%s%s",SignText,Currency,SpaceText,IntegerBuffer);
break;
case SP_SUCC_CURR:
// Currency Sign (Space) Value
SPrintf(Destination,"%s%s%s%s",Currency,SignText,SpaceText,IntegerBuffer);
break;
}
}
else
{
switch(SignPos)
{
case SP_PARENS:
// Sign Value (Space) Currency
SPrintf(Destination,"(%s%s%s%s)",SignText,IntegerBuffer,SpaceText,Currency);
break;
case SP_PREC_ALL:
// Sign Value (Space) Currency
SPrintf(Destination,"%s%s%s%s",SignText,IntegerBuffer,SpaceText,Currency);
break;
case SP_SUCC_ALL:
// Value (Space) Currency Sign
SPrintf(Destination,"%s%s%s%s",IntegerBuffer,SpaceText,Currency,SignText);
break;
case SP_PREC_CURR:
// Value (Space) Sign Currency
SPrintf(Destination,"%s%s%s%s",IntegerBuffer,SpaceText,SignText,Currency);
break;
case SP_SUCC_CURR:
// Value (Space) Currency Sign
SPrintf(Destination,"%s%s%s%s",IntegerBuffer,SpaceText,Currency,SignText);
break;
}
}
}
/* CreateSum(LONG Quantity):
*
* Create a string containing a monetary quantity formatted
* according to the current locale rules.
*/
STRPTR __regargs
CreateSum(LONG Quantity,BYTE UseCurrency)
{
STATIC UBYTE Buffer[100];
if(Locale)
ConvertMonetaryQuantity(Quantity,Buffer,UseCurrency);
else
SPrintf(Buffer,"%ld.%02ld",Quantity / 100,Quantity % 100);
return(Buffer);
}
/* LocalizeString(STRPTR *Strings,WORD From,WORD To):
*
* Localize an array of strings.
*/
VOID __regargs
LocalizeString(STRPTR *Strings,WORD From,WORD To)
{
WORD i,j;
for(i = From, j = 0 ; i <= To ; i++)
{
if(!Strings[j])
Strings[j++] = LocaleString(i);
}
}
/* LocalizeMenu(struct NewMenu *Menu,WORD From):
*
* Localize a NewMenu definition.
*/
VOID __regargs
LocalizeMenu(struct NewMenu *Menu,WORD From)
{
STRPTR Label,Shortcut;
while(Menu -> nm_Type != NM_END)
{
Shortcut = LocaleString(From);
if(Shortcut[0] && !Shortcut[1])
Label = Shortcut + 2;
else
{
Label = Shortcut;
Shortcut = NULL;
}
switch(Menu -> nm_Type)
{
case NM_TITLE:
Menu -> nm_Label = Label;
From++;
break;
case NM_ITEM:
case NM_SUB:
if(Menu -> nm_Label != NM_BARLABEL)
{
Menu -> nm_Label = Label;
Menu -> nm_CommKey = Shortcut;
From++;
}
break;
}
Menu++;
}
}
/* LocaleString(LONG ID):
*
* Obtain a string from the translation pool.
*/
STRPTR __regargs
LocaleString(LONG ID)
{
STRPTR Builtin;
if(ID < NumAppStrings && AppStrings[ID] . cca_ID == ID)
Builtin = AppStrings[ID] . cca_Str;
else
{
LONG i;
Builtin = "";
for(i = 0 ; i < NumAppStrings ; i++)
{
if(AppStrings[i] . cca_ID == ID)
{
Builtin = AppStrings[i] . cca_Str;
break;
}
}
}
if(Catalog)
{
STRPTR String = GetCatalogStr(Catalog,ID,Builtin);
if(String[0])
return(String);
else
return(Builtin);
}
else
return(Builtin);
}
STRPTR __saveds __stdargs
LocaleHookFunc(struct Hook *Hook,struct LayoutHandle *Handle,LONG ID)
{
return(LocaleString(ID));
}
STATIC LONG __saveds __asm
FormatDateHookFunc(register __a0 struct Hook *Hook,register __a1 UBYTE Char)
{
STRPTR String = Hook -> h_Data;
*String++ = Char;
Hook -> h_Data = String;
return(TRUE);
}
/* FormatStamp():
*
* Convert a date stamp into human readable
* form by taking the current locale parameters
* into account.
*/
BOOLEAN __regargs
FormatStamp(struct DateStamp *Stamp,STRPTR DateBuffer,STRPTR TimeBuffer,STRPTR BothBuffer,BOOLEAN SubstituteDay)
{
struct DateStamp Now;
// If no time stamp given, do with current time
if(!Stamp)
DateStamp(Stamp = &Now);
// Is the current locale available?
if(Locale)
{
struct Hook LocalHook = {{NULL}, (HOOKFUNC)FormatDateHookFunc};
// Combine date and time text?
if(BothBuffer && !SubstituteDay)
{
LocalHook . h_Data = BothBuffer;
FormatDate(Locale,Locale -> loc_DateTimeFormat,Stamp,&LocalHook);
StripSpaces(BothBuffer);
}
else
{
UBYTE LocalDateBuffer[40],
LocalTimeBuffer[40];
// Provide storage space
if(BothBuffer)
{
DateBuffer = LocalDateBuffer;
TimeBuffer = LocalTimeBuffer;
}
// Do we have a date buffer to fill?
if(DateBuffer)
{
// Are we to substitute the current day with
// text such as today, yesterday, etc.?
if(SubstituteDay)
{
struct DateStamp Today;
// Get the current time
DateStamp(&Today);
// Does the date refer to yesterday?
if(Stamp -> ds_Days == Today . ds_Days - 1)
strcpy(DateBuffer,GetLocaleStr(Locale,YESTERDAYSTR));
else
{
// Does the date refer to today?
if(Stamp -> ds_Days == Today . ds_Days)
strcpy(DateBuffer,GetLocaleStr(Locale,TODAYSTR));
else
{
// Does the date refer to tomorrow?
if(Stamp -> ds_Days == Today . ds_Days + 1)
strcpy(DateBuffer,GetLocaleStr(Locale,TOMORROWSTR));
else
SubstituteDay = NULL;
}
}
}
if(!SubstituteDay)
{
LocalHook . h_Data = DateBuffer;
FormatDate(Locale,Locale -> loc_DateFormat,Stamp,&LocalHook);
}
StripSpaces(DateBuffer);
}
if(TimeBuffer)
{
LocalHook . h_Data = TimeBuffer;
FormatDate(Locale,Locale -> loc_TimeFormat,Stamp,&LocalHook);
StripSpaces(TimeBuffer);
}
// Combine date and time
if(BothBuffer)
{
strcpy(BothBuffer,DateBuffer);
strcat(BothBuffer," ");
strcat(BothBuffer,TimeBuffer);
}
}
}
else
{
struct DateTime DateTime;
UBYTE LocalDateBuffer[40],
LocalTimeBuffer[40];
// Provide storage space
if(BothBuffer)
{
DateBuffer = LocalDateBuffer;
TimeBuffer = LocalTimeBuffer;
}
// No locale, so we will use dos.library instead.
CopyMem(Stamp,&DateTime . dat_Stamp,sizeof(struct DateStamp));
DateTime . dat_Format = FORMAT_DOS;
DateTime . dat_Flags = SubstituteDay ? DTF_SUBST : NULL;
DateTime . dat_StrDay = NULL;
DateTime . dat_StrDate = DateBuffer;
DateTime . dat_StrTime = TimeBuffer;
if(!DateToStr(&DateTime))
return(FALSE);
if(DateBuffer)
StripSpaces(DateBuffer);
if(TimeBuffer)
StripSpaces(TimeBuffer);
// Combine date and time
if(BothBuffer)
{
strcpy(BothBuffer,DateBuffer);
strcat(BothBuffer," ");
strcat(BothBuffer,TimeBuffer);
}
}
return(TRUE);
}
/* FormatTime(STRPTR Buffer,LONG Hours,LONG Minutes,LONG Seconds):
*
* Given hours, minutes and seconds, format this data into
* a human-readable string.
*/
VOID __regargs
FormatTime(STRPTR Buffer,LONG Hours,LONG Minutes,LONG Seconds)
{
if(Locale)
{
struct Hook LocalHook = {{NULL}, (HOOKFUNC)FormatDateHookFunc};
struct DateStamp Stamp;
Stamp . ds_Days = 0;
Stamp . ds_Minute = Hours * 60 + Minutes;
Stamp . ds_Tick = MAX(0,Seconds) * TICKS_PER_SECOND;
LocalHook . h_Data = Buffer;
if(Seconds < 0)
FormatDate(Locale,Locale -> loc_ShortTimeFormat,&Stamp,&LocalHook);
else
FormatDate(Locale,Locale -> loc_TimeFormat,&Stamp,&LocalHook);
}
else
{
if(Seconds < 0)
SPrintf(Buffer,"%02ld:%02ld",Hours,Minutes);
else
SPrintf(Buffer,"%02ld:%02ld:%02ld",Hours,Minutes,Seconds);
}
}